package com.maybach.core.ao.impl;

import com.maybach.common.BizResult;
import com.maybach.common.dto.UserInfoDTO;
import com.maybach.common.enums.BaseConstants.ResultCode;
import com.maybach.common.enums.PartnerStatusEnum;
import com.maybach.common.enums.user.UserStatusEnum;
import com.maybach.common.model.PartnerDO;
import com.maybach.common.model.UserDO;
import com.maybach.common.query.PartnerQuery;
import com.maybach.common.query.UserQuery;
import com.maybach.core.ao.UserAO;
import com.maybach.core.form.user.UserForm;
import com.maybach.core.form.user.UserQueryForm;
import com.maybach.core.form.user.UserUpdateStatusForm;
import com.maybach.core.manager.PartnerManager;
import com.maybach.core.manager.UserManager;
import com.maybach.dubbo.api.enums.AuditStatusEnum;
import com.maybach.util.*;
import com.maybach.util.query.support.BaseCriteria;
import com.maybach.util.query.support.PageResult;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by zhaoshuai on 16/1/14.
 */
@Component
public class UserAOImpl implements UserAO {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private UserManager userManager;

	@Autowired
	private PartnerManager partnerManager;

	@Override
	public Long addUser(UserForm userForm) {

		UserDO userDO = this.assembyUser(userForm);
		userDO.setStatus(UserStatusEnum.normal.getCode());

		userManager.insertSelective(userDO);
		return userDO.getId();
	}

	UserDO assembyUser(UserForm userForm) {
		UserDO userDO = new UserDO();
		userDO.setDescri(userForm.getDescri());
		userDO.setPartnerId(userForm.getPartnerId());
		userDO.setCertNo(userForm.getCertNo());
		userDO.setRealName(userForm.getRealName());
		userDO.setCertImgs(ImgUrlUtil.mergeList(userForm.getCertImgs()));
		userDO.setIsVerify(AuditStatusEnum.end.getStatus());
		userDO.setId(userForm.getId());
		userDO.setOutInviteCode(userForm.getOutInviteCode());
		userDO.setLoginName(userForm.getLoginName());
		userDO.setMobile(userForm.getLoginName());
		userDO.setMemo(userForm.getMemo());
		userDO.setExtNo(userForm.getExtNo());
		if (StringUtils.isNotBlank(userForm.getPassword())) {
			userDO.setPassword(Md5Util.simpleStringMD5(userForm.getPassword()));
		}
		userDO.setVisitingCardImgs(ImgUrlUtil.mergeList(userForm.getVisitingCardImgs()));
		return userDO;
	}

	UserForm assembyUser(UserDO userDO) {
		UserForm userForm = new UserForm();
		userForm.setDescri(userDO.getDescri());
		userForm.setPartnerId(userDO.getPartnerId());
		userForm.setCertNo(userDO.getCertNo());
		userForm.setRealName(userDO.getRealName());
		userForm.setCertImgs(ImgUrlUtil.parseList(userDO.getCertImgs()));
		userForm.setId(userDO.getId());
		userForm.setOutInviteCode(userDO.getOutInviteCode());
		userForm.setLoginName(userDO.getLoginName());
		userForm.setMobile(userDO.getLoginName());
		userForm.setMemo(userDO.getMemo());
		userForm.setExtNo(userDO.getExtNo());
		userForm.setVisitingCardImgs(ImgUrlUtil.parseList(userDO.getVisitingCardImgs()));
		return userForm;
	}

	@Override
	public UserForm getUserForm(Long id) {
		UserDO userDO = userManager.selectByPrimaryKey(id);
		return this.assembyUser(userDO);
	}

	@Override
	public void updateUser(UserForm userForm) {
		UserDO userDO = this.assembyUser(userForm);
		userManager.updateByPrimaryKeySelective(userDO);
	}

	@Override
	public boolean isAnotherUserExit(String loginName, Long id) {
		if (StringUtils.isBlank(loginName)) {
			return false;
		}
		UserQuery query = new UserQuery();
		UserQuery.Criteria criteria = query.or();
		criteria.andStatusNotEqualTo(UserStatusEnum.logical_delete.getCode());
		criteria.andLoginNameEqualTo(loginName);
		if (null != id) {
			criteria.andIdNotEqualTo(id);
		}

		return userManager.countByQuery(query) > 0;
	}

	@Override
	public PageResult<UserInfoDTO> queryUser(UserQueryForm queryForm) {
		PageResult<UserInfoDTO> result = new PageResult<UserInfoDTO>();
		// 1. 查询公司
		List<PartnerDO> partnerList = null;
		if (StringUtils.isNotBlank(queryForm.getCorpName())) {
			partnerList = this.queryPartner(queryForm.getCorpName());
		}
		// 2. 查询用户
		if (null != partnerList && partnerList.isEmpty()) { // 公司找不到 没有数据
			return result;
		}

		List<Long> list = CollectionUtil.transform(partnerList, new Transformer<PartnerDO, Long>() {
			@Override
			public Long transform(PartnerDO object) {
				return object.getId();
			}
		});

		UserQuery query = this.assemblyQuery(queryForm, list);
		return queryUserInfoDTO(result, partnerList, query);
	}

	private PageResult<UserInfoDTO> queryUserInfoDTO(PageResult<UserInfoDTO> result, List<PartnerDO> partnerList,
			UserQuery query) {
		PageResult<UserDO> userResult = userManager.selectByQueryWithPage(query);
		// 3. 数据转换
		result.setPageNo(userResult.getPageNo());
		result.setPageSize(userResult.getPageSize());
		result.setTotalCount(userResult.getTotalCount());

		if (CollectionUtils.isNotEmpty(userResult.getResult())) {
			Map<Long, PartnerDO> partnerMap = MapUtil.mapList(partnerList, new MapUtil.Transfer<Long, PartnerDO>() {
				@Override
				public Long transfer(PartnerDO obj) {
					return obj.getId();
				}
			});
			List<UserInfoDTO> userInfoDTOList = new ArrayList<UserInfoDTO>();
			for (UserDO user : userResult.getResult()) {
				PartnerDO partnerDO = partnerMap == null ? null : partnerMap.get(user.getPartnerId());
				UserInfoDTO userInfoDTO = this.assembly(user, partnerDO);
				userInfoDTOList.add(userInfoDTO);
			}
			result.setResult(userInfoDTOList);
		} else {
			result.setResult(new ArrayList<UserInfoDTO>());
		}

		return result;
	}

	@Override
	public PageResult<UserInfoDTO> queryAuthenticateUser(UserQueryForm queryForm) {
		PageResult<UserInfoDTO> result = new PageResult<UserInfoDTO>();
		// 1. 查询公司
		List<PartnerDO> partnerList = null;
		if (StringUtils.isNotBlank(queryForm.getCorpName())) {
			partnerList = this.queryPartner(queryForm.getCorpName());
		}
		// 2. 查询用户
		if (null != partnerList && partnerList.isEmpty()) { // 公司找不到 没有数据
			return result;
		}

		List<Long> list = CollectionUtil.transform(partnerList, new Transformer<PartnerDO, Long>() {
			@Override
			public Long transform(PartnerDO object) {
				return object.getId();
			}
		});

		/**
		 * 已认证的用户 对应的公司要存在
		 */
		UserQuery query = this.assemblyQuery(queryForm, list);
		for (BaseCriteria criteria : query.getOredCriteria()) {
			((UserQuery.Criteria) criteria).andPartnerIdIsNotNull();
		}

		return queryUserInfoDTO(result, partnerList, query);
	}

	private UserInfoDTO assembly(UserDO userDO, PartnerDO partnerDO) {
		UserInfoDTO userInfoDTO = new UserInfoDTO();
		userInfoDTO.setUserId(userDO.getId());
		userInfoDTO.setStatus(userDO.getStatus());
		userInfoDTO.setPerIsVerify(userDO.getIsVerify());
		userInfoDTO.setGmtCreate(userDO.getGmtCreate());
		userInfoDTO.setGmtModified(userDO.getGmtModified());
		userInfoDTO.setLoginName(userDO.getLoginName());
		userInfoDTO.setMemo(userDO.getMemo());
		userInfoDTO.setRealName(userDO.getRealName());
		UserDO inviteUser = this.getUserByInviteCode(userDO.getInviteCode());
		if (null != inviteUser) {
			userInfoDTO.setReferrerLoginName(inviteUser.getLoginName());
		}
		if (null == partnerDO && userDO.getPartnerId() != null) {
			partnerDO = partnerManager.selectByPrimaryKey(userDO.getPartnerId());
		}

		if (null != partnerDO) {
			userInfoDTO.setPartnerId(partnerDO.getId());
			userInfoDTO.setCorpIsVerify(partnerDO.getIsVerify());
			userInfoDTO.setCorpName(partnerDO.getCorpName());
		}
		return userInfoDTO;
	}

	UserDO getUserByInviteCode(String code) {
		if (StringUtils.isBlank(code)) {
			return null;
		}
		UserQuery query = new UserQuery();
		query.or().andInviteCodeEqualTo(code);

		List<UserDO> userDOList = userManager.selectByQuery(query);
		if (CollectionUtils.isNotEmpty(userDOList)) {
			return userDOList.get(0);
		}
		return null;
	}

	List<PartnerDO> queryPartner(String corpName) {
		if (StringUtils.isBlank(corpName)) {
			return null;
		}
		PartnerQuery query = new PartnerQuery();
		PartnerQuery.Criteria criteria = query.or();
		criteria.andCorpNameLike("%" + corpName + "%");
		criteria.andStatusNotEqualTo(PartnerStatusEnum.logical_delete.getCode());
		return partnerManager.selectByQuery(query);
	}

	protected UserQuery assemblyQuery(UserQueryForm userQueryForm, List<Long> partnerList) {
		AssertUtil.notNull(userQueryForm, "userQueryForm");
		UserQuery query = new UserQuery();
		UserQuery.Criteria criteria = query.or();
		query.setPageNo(userQueryForm.getPageNo());
		query.setPageSize(userQueryForm.getPageSize());

		if (StringUtils.isNotBlank(userQueryForm.getLoginName())) {
			criteria.andLoginNameLike("%" + userQueryForm.getLoginName() + "%");
		}
		if (StringUtils.isNotBlank(userQueryForm.getRealName())) {
			criteria.andRealNameLike("%" + userQueryForm.getRealName() + "%");
		}
		if (CollectionUtils.isNotEmpty(userQueryForm.getStatus())) {
			criteria.andStatusIn(userQueryForm.getStatus());
		}
		if (CollectionUtils.isNotEmpty(partnerList)) {
			criteria.andPartnerIdIn(partnerList);
		}
		query.setOrderByClause("id desc");
		return query;
	}

	/**
	 * 修改用户状态
	 *
	 * @param form
	 * @return
	 */
	@Override
	public BizResult updateUserStatus(UserUpdateStatusForm form) {
		BizResult result = new BizResult();
		if (null == form || null == form.getUserId() || form.getUserId() < 1L || null == form.getStatus()
				|| !UserStatusEnum.isRightStatusValue(form.getStatus())) {
			result.setResultCodeAndMsg(ResultCode.PARAM_ERROR);
			return result;
		}
		try {
			UserDO userDO = userManager.selectByPrimaryKey(form.getUserId());
			if (null == userDO) {
				result.setResultCodeAndMsg(ResultCode.PARAM_ERROR);
			} else if (userDO.getStatus().equals(form.getStatus())) {
				logger.warn("数据已更新[userId={}, status={}]", form.getUserId(), form.getStatus());
			} else {
				userDO.setStatus(form.getStatus());
				if (userManager.updateByPrimaryKeySelective(userDO) < 1) {
					result.setResultCodeAndMsg(ResultCode.UPDATE_FAIL);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			result.setResultCodeAndMsg(ResultCode.EXCEPTION);
		}
		return result;
	}

}
